package com.theme.passport.controller.app;

import com.theme.common.base.DateHandler;
import com.theme.common.base.StringHandler;
import com.theme.common.frame.exception.ErrorCode;
import com.theme.common.mvc.utils.PageUtils;
import com.theme.common.mvc.utils.RedisKeys;
import com.theme.common.mvc.view.R;
import com.theme.passport.annotation.Login;
import com.theme.passport.controller.app.utils.AppContextUtil;
import com.theme.passport.entity.UserEntity;
import com.theme.passport.entity.params.WeeksParams;
import com.theme.passport.entity.theme.UserSignInEntity;
import com.theme.passport.service.UserService;
import com.theme.passport.service.theme.UserSignInService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * APP用户签到表
 *
 * @author live
 * @email 870459550@qq.com
 * @date 2023-02-21 11:50:56
 */
@RestController
@RequestMapping("app/sign-in")
@Api("用户签到相关接口")
public class AppSignInController {

    private static final Logger logger = LoggerFactory.getLogger(AppSignInController.class);

    @Autowired
    private UserSignInService userSignInService;

    @Autowired
    private UserService userService;

    @Resource(name = "redisTemplate")
    private ValueOperations<String, String> redisCache;

    @Login
    @GetMapping("/list")
    @ApiOperation("获取用户本周签到记录")
    public R list(@RequestParam Map<String, Object> params){
        UserEntity currentUser = AppContextUtil.getCurrentUser();
        params.put("userId",currentUser.getId() +"");
        //查询本周开始时间和结束时间：
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long[] currentWeekTimeFrame = getCurrentWeekTimeFrame();
        String startTime = sdf.format(new Date(currentWeekTimeFrame[0]));
        String endTime = sdf.format(new Date(currentWeekTimeFrame[1]));
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        //根据时间范围查询
        PageUtils page = userSignInService.queryPage(params);
        List<WeeksParams> weekSignList = new ArrayList<>();
        try {
            List<UserSignInEntity> list = (List<UserSignInEntity>) page.getList();
            if (list == null || list.size()<=0){
                List<String> weekList = getWeekList();
                weekList.forEach(week -> {
                    WeeksParams weeksParams = new WeeksParams();
                    weeksParams.setWeek(week);
                    weeksParams.setSignin("0");
                    weekSignList.add(weeksParams);
                });
                return R.ok().put("weekSignList", weekSignList).put("signInTotal",0);
            }
            Map<String,String> weekMap = new HashMap<>();
            list.forEach(userSignInEntity -> {
                SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
                String startTimeTemp = sdf2.format(userSignInEntity.getSignInTime());
                weekMap.put(startTimeTemp,"1");
            });


            List<String> weekList = getWeekList();
            AtomicInteger signInTotal = new AtomicInteger();
            weekList.forEach(week -> {
                WeeksParams weeksParams = new WeeksParams();
                weeksParams.setWeek(week);
                String weekVal = weekMap.get(week);

                if (StringHandler.isEmpty(weekVal)){
                    weekMap.put(week,"0");
                    weeksParams.setSignin("0");
                    String stringTodayYMD = DateHandler.getStringTodayYMD();
                    Date currentDate = DateHandler.strToDateLong(stringTodayYMD + " 00:00:00");
                    Date weekDate = DateHandler.strToDateLong(week + " 00:00:00");
                    //logger.info("currentDate={},weekDate={},result={}",currentDate,weekDate,currentDate.before(weekDate));
                    if (!currentDate.before(weekDate) && !stringTodayYMD.equals(week)){
                        signInTotal.set(0);
                    }
                }else {
                    signInTotal.set(signInTotal.get() + 1);
                    weeksParams.setSignin("1");
                }
                weekSignList.add(weeksParams);
            });
            return R.ok().put("weekSignList", weekSignList).put("signInTotal",signInTotal.get());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Login
    @GetMapping("/latelyDay7")
    @ApiOperation("获取用户本周签到记录(最近七天)")
    public R latelyDay7(@RequestParam Map<String, Object> params){
        UserEntity currentUser = AppContextUtil.getCurrentUser();
        params.put("userId",currentUser.getId() +"");
        //查询本周开始时间和结束时间：
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获取当前时间，当前时间减去7天
        String endDate = DateHandler.getNowStrDate();
        Date startDate = DateHandler.addDateDays(new Date(), -7);

        String startTime = sdf.format(startDate);
        String endTime = sdf.format(endDate);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        //根据时间范围查询
        PageUtils page = userSignInService.queryPage(params);
        List<WeeksParams> weekSignList = new ArrayList<>();
        try {
            List<UserSignInEntity> list = (List<UserSignInEntity>) page.getList();
            if (list == null || list.size()<=0){
                return R.ok().put("latelyDay7SignList", weekSignList);
            }
            Map<String,String> weekMap = new HashMap<>();
            list.forEach(userSignInEntity -> {
                SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
                String startTimeTemp = sdf2.format(userSignInEntity.getSignInTime());
                weekMap.put(startTimeTemp,"1");
            });
            List<String> weekList = getWeekList();
            weekList.forEach(week -> {
                WeeksParams weeksParams = new WeeksParams();
                weeksParams.setWeek(week);
                String weekVal = weekMap.get(week);
                if (StringHandler.isEmpty(weekVal)){
                    weekMap.put(week,"0");
                    weeksParams.setSignin("0");
                }else {
                    weeksParams.setSignin("1");
                }
                weekSignList.add(weeksParams);
            });
            return R.ok().put("latelyDay7SignList", weekSignList);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Login
    @PostMapping("/add")
    @ApiOperation("添加用户签到记录接口")
    public R add(@RequestParam Map<String, Object> params){
        UserEntity currentUser = AppContextUtil.getCurrentUser();
        // 查询用户今天是否已经签到过了
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date todayDate = DateHandler.getStartTime(new Date());
        String todayTime = sdf.format(todayDate.getTime());
        params.put("userId",currentUser.getId() +"");
        params.put("todayTime",todayTime);
        PageUtils page = userSignInService.queryPage(params);
        List<?> list = page.getList();
        if (list != null && list.size() > 0){
            return R.error("您今天已经签到过了!");
        }
        //给用户添加签到
        UserSignInEntity userSignIn = new UserSignInEntity();
        userSignIn.setUserId(currentUser.getId());
        userSignIn.setSignInTime(new Date());
        userSignIn.setCreateTime(new Date());
        userSignInService.save(userSignIn);

        return R.ok();
    }

    @Login
    @PostMapping("/supplementary")
    @ApiOperation("用户补签记录接口")
    public R supplementary(@RequestParam("supplementaryDate") String supplementaryDate){
        UserEntity currentUser = AppContextUtil.getCurrentUser();
        // 查询用户今天是否已经签到过了
        Map<String, Object> params = new HashMap<>();
        params.put("userId",currentUser.getId() +"");
        params.put("todayTime",supplementaryDate);
        PageUtils page = userSignInService.queryPage(params);
        List<?> list = page.getList();
        if (list != null && list.size() > 0){
            return R.error("您已经补签过了!");
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date supplementary = sdf.parse(supplementaryDate);
            //给用户添加签到
            UserSignInEntity userSignIn = new UserSignInEntity();
            userSignIn.setUserId(currentUser.getId());
            userSignIn.setSignInTime(supplementary);
            userSignIn.setCreateTime(new Date());
            userSignInService.save(userSignIn);

            //本周开始时间结束时间
            long[] currentWeekTimeFrame = getCurrentWeekTimeFrame();
            String startTime = sdf.format(new Date(currentWeekTimeFrame[0]));
            String endTime = sdf.format(new Date(currentWeekTimeFrame[1]));
            String supplementaryUser = startTime+"_"+endTime+":"+currentUser.getId(); //日期加用户id
            String supplementarykey = RedisKeys.USER_SUPPLEMENTARY_DATE.concat(supplementaryUser);
            redisCache.set(supplementarykey,supplementaryDate,14, TimeUnit.DAYS); //存储时间 40 天
            return R.ok();
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Login
    @GetMapping("/isSupplementaryByWeek")
    @ApiOperation("判断用户本周是否补签过")
    public R isSupplementaryByWeek(){
        UserEntity currentUser = AppContextUtil.getCurrentUser();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //本周开始时间结束时间
        long[] currentWeekTimeFrame = getCurrentWeekTimeFrame();
        String startTime = sdf.format(new Date(currentWeekTimeFrame[0]));
        String endTime = sdf.format(new Date(currentWeekTimeFrame[1]));
        String supplementaryUser = startTime+"_"+endTime+":"+currentUser.getId(); //日期加用户id
        String supplementarykey = RedisKeys.USER_SUPPLEMENTARY_DATE.concat(supplementaryUser);
        String result = redisCache.get(supplementarykey);
        if (!StringHandler.isEmpty(result)){
            return R.error(ErrorCode.USER_SUPPLEMENTARY_EXIST.getCode(),ErrorCode.USER_SUPPLEMENTARY_EXIST.getMsg())
                    .put("supplementaryDate",result);
        }
        return R.ok("本周没有补签记录");
    }

    @Login
    @PostMapping("/isExistSupplementaryDate")
    @ApiOperation("根据用户传的日期判断用户是否已经补签过")
    public R isSupplementaryExist(@RequestParam("supplementaryDate") String supplementaryDate){
        UserEntity currentUser = AppContextUtil.getCurrentUser();
        // 查询用户今天是否已经签到过了
        Map<String, Object> params = new HashMap<>();
        params.put("userId",currentUser.getId() +"");
        params.put("todayTime",supplementaryDate);
        PageUtils page = userSignInService.queryPage(params);
        List<?> list = page.getList();
        if (list != null && list.size() > 0){
            return R.error("您已经签到或者补签过了!");
        }
        return R.ok("还未签到或者补签!");
    }

    @Login
    @PostMapping("/addVipDays")
    @ApiOperation("给用户新增vip时间和天数接口:定时任务检测VIP过期时间")
    public R addVipDays(@RequestParam("days") int days){

        // 获取当月时间
        String nowMonthStrDate = DateHandler.getNowMonthStrDate();
        UserEntity currentUser = AppContextUtil.getCurrentUser();
        String userId = nowMonthStrDate+":"+currentUser.getId() +""; //日期加用户id
        String signInKey = RedisKeys.USER_SIGNIN.concat(userId);

        String result = redisCache.get(signInKey);
        if (!StringHandler.isEmpty(result)){
            return R.error(ErrorCode.USER_SIGN_IN_EXIST.getCode(),ErrorCode.USER_SIGN_IN_EXIST.getMsg());
        }
        //修改用户为VIP和新增过期时间
        UserEntity user = userService.updateUserVipDays(currentUser.getId(), days);
        redisCache.set(signInKey,"1",50, TimeUnit.DAYS); //存储时间 40 天
        user.setPassword(null);
        return R.ok().put("user",user);
    }

    public static long[] getCurrentWeekTimeFrame() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        //start of the week
        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calendar.add(Calendar.DAY_OF_YEAR,-1);
        }
        calendar.add(Calendar.DAY_OF_WEEK, -(calendar.get(Calendar.DAY_OF_WEEK) - 2));
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        long startTime = calendar.getTimeInMillis();
        //end of the week
        calendar.add(Calendar.DAY_OF_WEEK, 6);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        long endTime = calendar.getTimeInMillis();
        return new long[]{startTime, endTime};
    }

    private List<String> getWeekList() throws ParseException {
        List<String> weekList = new ArrayList<>();
        long[] currentWeekTimeFrame = getCurrentWeekTimeFrame();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String startTime = sdf.format(new Date(currentWeekTimeFrame[0]));
        String endTime = sdf.format(new Date(currentWeekTimeFrame[1]));
        String week2 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 1));
        String week3 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 2));
        String week4 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 3));
        String week5 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 4));
        String week6 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 5));
        weekList.add(startTime);
        weekList.add(week2);
        weekList.add(week3);
        weekList.add(week4);
        weekList.add(week5);
        weekList.add(week6);
        weekList.add(endTime);
        return weekList;
    }

    private List<String> getLatelyDay7List(String startTime,String endTime) throws ParseException {
        List<String> weekList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String week2 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), -1));
        String week3 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), -2));
        String week4 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), -3));
        String week5 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), -4));
        String week6 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), -5));
        weekList.add(startTime);
        weekList.add(week2);
        weekList.add(week3);
        weekList.add(week4);
        weekList.add(week5);
        weekList.add(week6);
        weekList.add(endTime);
        return weekList;
    }


    public static void main(String[] args) throws ParseException {
        long[] currentWeekTimeFrame = getCurrentWeekTimeFrame();
        System.out.println("AppSignInController.main: 本周开始时间和结束时间" );
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String startTime = sdf.format(new Date(currentWeekTimeFrame[0]));
        String endTime = sdf.format(new Date(currentWeekTimeFrame[1]));
        System.out.println(startTime + " >> " + endTime);
        String week1 = startTime;
        String week2 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 1));
        String week3 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 2));
        String week4 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 3));
        String week5 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 4));
        String week6 = sdf.format(DateHandler.addDateDays(sdf.parse(startTime), 5));
        String week7 = endTime;
        System.out.println("AppSignInController.main-周一到周天");
        System.out.println("AppSignInController.main1:"+ week1);
        System.out.println("AppSignInController.main2:"+ week2);
        System.out.println("AppSignInController.main3:"+ week3);
        System.out.println("AppSignInController.main4:"+ week4);
        System.out.println("AppSignInController.main5:"+ week5);
        System.out.println("AppSignInController.main6:"+ week6);
        System.out.println("AppSignInController.main7:"+ week7);

        System.out.println("AppSignInController.main: 获取今天时间时间加7天" );
        Date todayDate = DateHandler.getStartTime(new Date());
        String todayTime = sdf.format(todayDate.getTime());
        System.out.println(todayTime);

        //从今天开始起算然后加7天时间
        Date expiresTime = DateHandler.addDateDays(new Date(), 7);
        String expiresTime2 = sdf.format(expiresTime.getTime());
        System.out.println(expiresTime2);

        String nowMonthStrDate = DateHandler.getNowMonthStrDate();
        String userId = nowMonthStrDate+":"+ 12 +""; //日期加用户id
        String signInKey = RedisKeys.USER_SIGNIN.concat(userId);
        System.out.println("AppSignInController.main:" + signInKey);
    }

}
